package com.example.demo.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.example.demo.constant.Constant;
import com.example.demo.service.ExportService;
import com.example.demo.utils.exportUtils.EasyExcelUtils;
import com.example.demo.utils.exportUtils.ExportDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @author xiaobeibei@gogpay.cn
 * @date 2023-12-08 14:35
 */
@Service
public class ExportServiceImpl implements ExportService {

    private static final Logger LOGGER= LoggerFactory.getLogger(ExportServiceImpl.class);

    private final RabbitTemplate rabbitTemplate;
    private final StringRedisTemplate redisTemplate;

    private List<ExportDTO> list = new ArrayList<>();

    @Autowired
    public ExportServiceImpl(RabbitTemplate rabbitTemplate, StringRedisTemplate redisTemplate) {
        this.rabbitTemplate = rabbitTemplate;
        this.redisTemplate = redisTemplate;
    }

    /**
     * 导出列表Excel
     *
     * @param form     前端入参
     * @param response 导出位置
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void exportExcel(JSONObject form, HttpServletResponse response) {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        try {
            EasyExcel.write(response.getOutputStream(),ExportDTO.class)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    // 参数为sheet名
                    .sheet().doWrite(list);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 异步导出大量数据（使用mq消息队列实现）
     *
     * @param form 前端入参
     */
    @Override
    public void exportBigData(JSONObject form) {
        // 发送mq，异步导出开卡申请记录
        LOGGER.info("【某业务】发送异步导出开卡申请记录mq，参数：{}", form);
        rabbitTemplate.convertAndSend(Constant.EXPORT_QUEUE, JSON.toJSONString(form));
    }

    /**
     * 执行导出任务
     */
    @Override
    public void export(JSONObject form) {
        // 获取文件M密码
        String filmPassword = this.getFilmPassword();
        EasyExcelUtils easyExcelUtils = new EasyExcelUtils();
        try {
            String fileUrl = easyExcelUtils.exportByExcel(list, ExportDTO.class, filmPassword);
            // 保存redis
            String key="export:key";
            // 只保留最新导出地址，之前的删除
            if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
                // 删除已存在key
                redisTemplate.delete(key);
            }
            // 更新导出文件
            redisTemplate.opsForValue().set(key, JSON.toJSONString(fileUrl), 15, TimeUnit.DAYS);
        } catch (IOException e) {
            LOGGER.error("异步导出文件失败，失败原因，{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 获取文件密码
     *
     * @return 文件密码
     */
    private String getFilmPassword() {
        Random random = new Random();
        Double p = (1 + random.nextDouble()) * Math.pow(10, 6);
        String s = String.valueOf(p);
        return s.substring(1, 6 + 1);
    }
}
